package com.share.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.common.core.exception.ServiceException;
import com.share.common.security.utils.SecurityUtils;
import com.share.device.domain.Cabinet;
import com.share.device.domain.CabinetSlot;
import com.share.device.domain.CabinetType;
import com.share.device.domain.PowerBank;
import com.share.device.mapper.CabinetMapper;
import com.share.device.mapper.CabinetSlotMapper;
import com.share.device.mapper.CabinetTypeMapper;
import com.share.device.mapper.PowerBankMapper;
import com.share.device.service.ICabinetService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ZhouShuang
 * @version 17
 * @Title
 * @date 2025/10/10 上午11:44
 */
@RequiredArgsConstructor
@Service
public class CabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet> implements ICabinetService {

    private final CabinetMapper cabinetMapper;
    private final CabinetSlotMapper cabinetSlotMapper;
    private final PowerBankMapper powerBankMapper;
    private final CabinetTypeMapper cabinetTypeMapper;

    /**
     * 查询充电宝柜机列表
     *
     * @param cabinet
     * @return
     */
    @Override
    public List<Cabinet> selectCabinetList(Cabinet cabinet) {
        return cabinetMapper.selectCabinetList(cabinet);
    }

    /**
     * 搜索未使用的充电宝
     *
     * @param keyword
     * @return
     */
    @Override
    public List<Cabinet> searchNoUserList(String keyword) {
        LambdaQueryWrapper<Cabinet> cabinetLambdaQueryWrapper = new LambdaQueryWrapper<>();
        cabinetLambdaQueryWrapper.like(Cabinet::getCabinetNo, keyword);
        cabinetLambdaQueryWrapper.eq(Cabinet::getStatus, "0");
        return this.list(cabinetLambdaQueryWrapper);
    }

    /**
     * 获取充电宝柜机详细信息
     *
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> getAllInfo(Long id) {
        //获取充电宝柜机信息
        Cabinet cabinet = this.getById(id);
        //获取充电宝插槽信息
        List<CabinetSlot> cabinetSlotList = cabinetSlotMapper.selectList(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));
        //获取充电宝柜机的插槽中有充电宝的插槽信息的id列表
        List<Long> powerBankIds = cabinetSlotList.stream().map(CabinetSlot::getPowerBankId).filter(Objects::nonNull).toList(); //过滤掉没有充电宝的插槽
        //判断id列表是否为空或者长度为0
        if (!CollectionUtils.isEmpty(powerBankIds)) {
            List<PowerBank> powerBankList = powerBankMapper.selectList(new LambdaQueryWrapper<PowerBank>().in(PowerBank::getId, powerBankIds));
            Map<Long, PowerBank> powerBankMap = powerBankList.stream().collect(Collectors.toMap(PowerBank::getId, PowerBank -> PowerBank));
            cabinetSlotList.forEach(cabinetSlot -> cabinetSlot.setPowerBank(powerBankMap.getOrDefault(cabinetSlot.getPowerBankId(), null)));
        }
        return Map.of("cabinet", cabinet, "cabinetSlotList", cabinetSlotList); //返回不可变的map
    }

    /**
     * 添加充电宝柜机信息
     *
     * @param cabinet
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveCabinet(Cabinet cabinet) {
        //判断柜机编号是否已经存在
        long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
        if (count > 0) {
            throw new ServiceException("该柜机编号已经存在");
        }

        //根据柜机类别id查询柜机类别
        CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());

        //设置总插槽数和可用插槽数
        cabinet.setTotalSlots(cabinetType.getTotalSlots());
        cabinet.setFreeSlots(cabinetType.getTotalSlots());
        cabinet.setUsedSlots(0);
        cabinet.setAvailableNum(0);
        cabinet.setCreateBy(SecurityUtils.getUsername());
        cabinet.setCreateTime(new Date());
        this.save(cabinet);

        //添加充电宝插槽信息
        fillCabinetSlot(cabinet, cabinetType);
        return 1;
    }

    /**
     * 修改充电宝柜机信息
     *
     * @param cabinet
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateCabinet(Cabinet cabinet) {
        //1.获取旧充电宝柜机信息
        Cabinet oldCabinet = this.getById(cabinet.getId());
        //2.判断旧充电宝信息是否存在
        if (oldCabinet == null) {
            throw new ServiceException("不存在该充电宝柜机信息");
        }

        //3.判断该柜机是否已经投放
        if (!Objects.equals("0", oldCabinet.getStatus())) {
            throw new ServiceException("该充电宝已经投放，无法修改");
        }

        //4.判断柜机编号是否已经存在
        if (!oldCabinet.getCabinetNo().equals(cabinet.getCabinetNo())) {
            long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
            if (count > 0) {
                throw new ServiceException("该柜机编号已经存在");
            }
        }

        //5.判断是否修改了柜机类型
        if (!Objects.equals(oldCabinet.getCabinetTypeId(), cabinet.getCabinetTypeId())) {
            //获取新的柜机类型信息
            CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());

            //重新设置充电宝柜机的总插槽数和可用插槽数
            //设置总插槽数和可用插槽数
            cabinet.setTotalSlots(cabinetType.getTotalSlots());
            cabinet.setFreeSlots(cabinetType.getTotalSlots());
            cabinet.setUsedSlots(0);
            cabinet.setAvailableNum(0);

            //删除旧的充电宝插槽信息
            cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));
            //重新添加新的充电宝插槽信息
            fillCabinetSlot(cabinet, cabinetType);
        }
        cabinet.setUpdateBy(SecurityUtils.getUsername());
        cabinet.setUpdateTime(new Date());
        return cabinetMapper.updateById(cabinet);
    }

    /**
     * 根据柜机编号查询对应的柜机信息
     *
     * @param cabinetNo
     * @return
     */
    @Override
    public Cabinet getByCabinetNo(String cabinetNo) {
        return cabinetMapper.selectOne(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinetNo));
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeBatchByIds(Collection<?> list){
        cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().in(CabinetSlot::getCabinetId,list));
        return super.removeBatchByIds(list);
    }

    /**
     * 填充充电宝插槽信息
     * @param cabinet
     * @param cabinetType
     */
    private void fillCabinetSlot(Cabinet cabinet, CabinetType cabinetType) {
        int size = cabinetType.getTotalSlots();
        for (int i = 0; i < size; i++) {
            CabinetSlot cabinetSlot = new CabinetSlot();
            cabinetSlot.setCabinetId(cabinet.getId());
            cabinetSlot.setSlotNo(i + 1 + "");
            cabinetSlot.setCreateBy(SecurityUtils.getUsername());
            cabinetSlot.setCreateTime(new Date());
            cabinetSlotMapper.insert(cabinetSlot);
        }
    }
}
